home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d20 / dorskel2.arc / XBBSMSG.ARC / GETPUT.C next >
C/C++ Source or Header  |  1991-12-05  |  15KB  |  594 lines

  1. /* primitives for manipulating XBBS message areas
  2.    this code hacked out in one sitting by Mark Kimes 06/25/91
  3.    compiles; no guarantee that it works. */
  4.  
  5. /* I'm not quite sure how locking works under DOS-OS/2.  Does the seek
  6.    to a locked record fail, or the read/write?  This code assumes that
  7.    either could fail.  It locks for all writes, no reads. */
  8.  
  9. #ifndef __TURBOC__
  10.     #define INCL_DOS
  11.     #include <os2.h>            /* for DosSleep() */
  12.     #include <sys/locking.h>
  13. #endif
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #include <io.h>
  17. #include <fcntl.h>
  18. #include <share.h>
  19. #include <stdlib.h>
  20. #include <stdio.h>
  21. #include <string.h>
  22. #include <errno.h>
  23. #include "xmsg.h"
  24.  
  25. #ifdef __TURBOC__
  26.     #define LK_LOCK     1
  27.     #define LK_UNLCK    2
  28.     #define DosSleep(x) sleep(1)
  29.     /* replacement for MSC's locking() in this module */
  30.     int pascal locking (int handle,int type,long length);  
  31.     #define _fastcall pascal
  32. #endif
  33.  
  34.  
  35. /* external variables referenced */
  36.  
  37. extern char *msgpath;
  38.  
  39. /* external functions referenced */
  40.  
  41. /* global variables created here */
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49. int _fastcall get_text (char **hold,XMSG *msg,unsigned int areano,
  50.                         unsigned int messno) {
  51.  
  52.  /* loads text for XMSG *msg message #messno from areano #areano into
  53.     **hold (allocates here, caller must free).  Can modify *msg if
  54.     message hasn't been previously TREATED.  UNLZSSs if message was
  55.     compressed. */
  56.  
  57.     int          once,reduced = 0,handle;
  58.     char         *tempo;
  59.     char         filename[257];
  60.     unsigned int temp,len;
  61.     long         pos;
  62.  
  63.  
  64.     if(!msg->length) return MSG_NOTEXT;
  65.     if(msg->length > 65500U) msg->length = 65500U;
  66.     *hold = NULL;
  67.  
  68.     /* open text file */
  69.  
  70.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  71.     once = 0;
  72.     while ((handle = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IREAD | S_IWRITE)) == -1) {
  73.         if (errno == EACCES) {
  74.             once++;
  75.             if (once > 10) {
  76.                 return MSG_NOACCESS;
  77.             }
  78.             DosSleep(1000L);
  79.         }
  80.         else {
  81.             return MSG_NOOPEN;
  82.         }
  83.     }
  84.  
  85.     temp = msg->length;
  86.  
  87.     /* seek to position */
  88.  
  89.     once = 0;
  90.     while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  91.         if (once < 10) {
  92.             once++;
  93.             DosSleep(1000L);
  94.         }
  95.         else {
  96.             close(handle);
  97.             return MSG_NOSEEK;
  98.         }
  99.     }
  100.  
  101.     /* load text */
  102.  
  103.     if(msg->length > 65500U) msg->length = 65500U;
  104.  
  105. ReTry:
  106.     *hold = (char *)malloc(msg->length + 1);
  107.     if (*hold == NULL) {
  108.         if (msg->length > 1024 && !(msg->m_attr & MSGPACKED)) {
  109.             msg->length -= 256;
  110.             reduced = 1;
  111.             goto ReTry;
  112.         }
  113.         else {
  114.             close(handle);
  115.             return MSG_NOMEM;
  116.         }
  117.     }
  118.  
  119.     memset(*hold,0,msg->length);
  120.  
  121.     once = 0;
  122.     for(;;) {
  123.         pos = tell(handle);
  124.         len = (unsigned int)read(handle,*hold,msg->length);
  125.         if(!len || len == 65535U) {
  126.             once++;
  127.             if(once < 10) {
  128.                 lseek(handle,pos,SEEK_SET);
  129.                 DosSleep(500L);
  130.             }
  131.             else {
  132.                 close(handle);
  133.                 free(*hold);
  134.                 *hold = NULL;
  135.                 return MSG_NOREAD;
  136.             }
  137.         }
  138.         else if(len < (msg->length - 1)) {
  139.             reduced = 1;
  140.             break;
  141.         }
  142.         else break;
  143.     }
  144.  
  145.     close(handle);
  146.     tempo = *hold;
  147.     tempo[msg->length - 1] = 0;
  148.     tempo[msg->length] = 0;
  149.  
  150.     /* treat text if necessary */
  151.  
  152.     tempo = *hold;
  153.     if(!(msg->m_attr & MSGTREATED) &&
  154.        /* !(currarea->attr & ANSI) && */ !(msg->m_attr & MSGPACKED)) {
  155.         while (*tempo) {
  156.             if(*tempo == '\x8d' || *tempo == '\n') {
  157.                 memmove(tempo,&tempo[1],msg->length - ((unsigned int)tempo -
  158.                         (unsigned int)*hold));
  159.                 msg->length--;
  160.                 if(!msg->length) break;
  161.             }
  162.             else tempo++;
  163.         }
  164.         if(*(tempo - 1) != '\r' && tempo > *hold) {
  165.             *tempo = '\r';
  166.             tempo[1] = 0;
  167.         }
  168.  
  169.         /* rewrite treated text */
  170.  
  171.         if(!reduced && temp > ((unsigned int)strlen(*hold) + 1) && **hold) {
  172.             msg->length = (unsigned int)strlen(*hold) + 1;
  173.             sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  174.         if ((handle = sopen(filename,O_RDWR | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD)) == -1)
  175.               goto OkayThenDont;
  176.             once = 0;
  177.             while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  178.                 if (once < 10) {
  179.                     once++;
  180.                     DosSleep(100L);
  181.                 }
  182.                 else {
  183.                     close(handle);
  184.                     goto OkayThenDont;
  185.                 }
  186.             }
  187.             if(!locking(handle,LK_LOCK,(long)(msg->length + 1))) {
  188.                 write(handle,*hold,strlen(*hold));
  189.                 write(handle,"\0",1);
  190.                 lseek(handle,msg->start,SEEK_SET);
  191.                 locking(handle,LK_UNLCK,(long)(msg->length + 1));
  192.                 close(handle);
  193.  
  194.                 /* rewrite header for treated text */
  195.  
  196.                 msg->m_attr |= MSGTREATED;
  197.                 put_mess(msg,areano,messno);
  198.                 temp = msg->length;
  199.             }
  200.         }
  201.     }
  202.  
  203.     /* UnLZSS compressed text */
  204.  
  205.     if(msg->m_attr & MSGPACKED && !reduced) {
  206.        if(unpack_msg(msg,hold) == NULL) {   /* extern routine */
  207.            if(*hold) free(*hold);
  208.            *hold = NULL;
  209.            return MSG_NOUNLZSS;
  210.        }
  211.     }
  212.  
  213.     /* wrapup */
  214.  
  215. OkayThenDont:
  216.  
  217.     msg->length = temp;
  218.     if(reduced) return MSG_REDUCED;
  219.     return MSG_NOERR;
  220. }
  221.  
  222.  
  223.  
  224.  
  225. int _fastcall append_text (XMSG *msg,char *hold,unsigned int areano,
  226.                            unsigned int messno) {
  227.  
  228.  /* appends text for XMSG *msg, message #messno in area #areano with
  229.     text in *hold.  updates msg->length and msg->start */
  230.  
  231.     unsigned int messlen = 0;
  232.     int          handle,once;
  233.     long         pos;
  234.     char         filename[257];
  235.  
  236.  
  237.     if (hold == NULL || !*hold) return MSG_NOTEXT;
  238.  
  239.     /* open text file */
  240.  
  241.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  242.     once = 0;
  243.     while ((handle = sopen(filename,O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  244.         if (errno == EACCES) {
  245.             if(once < 10) {
  246.                 DosSleep(1000L);
  247.                 once++;
  248.             }
  249.             else {
  250.                 return MSG_NOACCESS;
  251.             }
  252.         }
  253.         else return MSG_NOOPEN;
  254.     }
  255.  
  256.     /* seek to position */
  257.  
  258.     once = 0;
  259.     while (lseek(handle,0L,SEEK_END) == -1L) {
  260.         if (once < 10) {
  261.             once++;
  262.             DosSleep(100L);
  263.         }
  264.         else {
  265.             close(handle);
  266.             return MSG_NOSEEK;
  267.         }
  268.     }
  269.  
  270.     /* lock, write, unlock */
  271.  
  272.     if(!locking(handle,LK_LOCK,65535L)) {
  273.         pos = tell(handle);
  274.         messlen += write(handle,hold,sizeof(char) * strlen(hold));
  275.         write(handle,"\0",1);
  276.         lseek(handle,pos,SEEK_SET);
  277.         locking(handle,LK_UNLCK,65535L);
  278.         messlen += 2;
  279.         msg->length = messlen;
  280.         msg->start = pos;
  281.         if(msg->length > 65500U) msg->length = 65500U;
  282.         close(handle);
  283.         return MSG_NOERR;
  284.     }
  285.  
  286.     close(handle);
  287.     return MSG_NOLOCK;
  288. }
  289.  
  290.  
  291.  
  292.  
  293. int _fastcall replace_text (XMSG *msg,char *hold,unsigned int areano,
  294.                             unsigned int messno) {
  295.  
  296.  /* call this to replace text for XMSG *msg, message #messno, areano
  297.     #areano with text in *hold.  Will append instead of replace if
  298.     there's not enough room in existing allocation.  Updates msg->length
  299.     (and msg->start) */
  300.  
  301.     unsigned int messlen = 0;
  302.     int          handle,once;
  303.     char         filename[257];
  304.  
  305.  
  306.     if (hold == NULL || !*hold) return MSG_NOTEXT;
  307.  
  308.     /* decide whether to append or replace */
  309.  
  310.     if(strlen(hold) > msg->length - 2)
  311.       return append_text(msg,hold,areano,messno);
  312.  
  313.     /* open text file */
  314.  
  315.     sprintf(filename,"%sXTEXT.%03x",msgpath,areano);
  316.     once = 0;
  317.     while ((handle = sopen(filename,O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  318.         if (errno == EACCES) {
  319.             if(once < 10) {
  320.                 DosSleep(1000L);
  321.                 once++;
  322.             }
  323.             else {
  324.                 return MSG_NOACCESS;
  325.             }
  326.         }
  327.         else return MSG_NOOPEN;
  328.     }
  329.  
  330.     /* seek to position */
  331.  
  332.     once = 0;
  333.     while (lseek(handle,msg->start,SEEK_SET) == -1L) {
  334.         if (once < 10) {
  335.             once++;
  336.             DosSleep(100L);
  337.         }
  338.         else {
  339.             close(handle);
  340.             return MSG_NOSEEK;
  341.         }
  342.     }
  343.  
  344.     /* lock, write, unlock */
  345.  
  346.     if(!locking(handle,LK_LOCK,65535L)) {
  347.         messlen += write(handle,hold,sizeof(char) * strlen(hold));
  348.         write(handle,"\0",1);
  349.         lseek(handle,msg->start,SEEK_SET);
  350.         locking(handle,LK_UNLCK,65535L);
  351.         messlen += 2;
  352.         msg->length = messlen;
  353.         close(handle);
  354.         if(msg->length > 65500U) msg->length = 65500U;
  355.         return MSG_NOERR;
  356.     }
  357.  
  358.     close(handle);
  359.     return MSG_NOLOCK;
  360. }
  361.  
  362.  
  363.  
  364.  
  365. int _fastcall get_mess (XMSG *msg,unsigned int areano,unsigned int messno) {
  366.  
  367.  /* fill XMSG *msg with data for message #messno in area #areano */
  368.  
  369.     int          handle,once;
  370.     char         filename[257];
  371.     unsigned int len;
  372.     long         pos;
  373.  
  374.  
  375.     /* open data file */
  376.  
  377.     sprintf(filename,"%sXDATA.%03x",msgpath,areano);
  378.     if (messno < 1) messno = 1;
  379.     once = 0;
  380.     while ((handle = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  381.         if (errno == EACCES) {
  382.             if(once < 10) {
  383.                 once++;
  384.                 DosSleep(1000L);
  385.             }
  386.             else {
  387.                 return MSG_NOACCESS;
  388.             }
  389.          }
  390.          else {
  391.              return MSG_NOOPEN;
  392.          }
  393.     }
  394.  
  395.     /* seek to position */
  396.  
  397.     once = 0;
  398.     while (lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET) == -1L) {
  399.         if(once < 10) {
  400.             once++;
  401.             DosSleep(100L);
  402.         }
  403.         else {
  404.             close(handle);
  405.             return MSG_NOSEEK;
  406.         }
  407.     }
  408.  
  409.     /* read and wrapup */
  410.  
  411.     once = 0;
  412.     memset(msg,0,sizeof(XMSG));
  413.     pos = tell(handle);
  414.     for(;;) {
  415.         len = (unsigned int)read(handle,msg,sizeof(XMSG));
  416.         if(!len || len == 65535U) {
  417.             once++;
  418.             if(once < 10) {
  419.                 lseek(handle,pos,SEEK_SET);
  420.                 DosSleep(500L);
  421.             }
  422.             else {
  423.                 close(handle);
  424.                 return MSG_NOREAD;
  425.             }
  426.         }
  427.         else if(len < sizeof(XMSG)) {
  428.             close(handle);
  429.             return MSG_PARTREAD;
  430.         }
  431.         else break;
  432.     }
  433.  
  434.     close(handle);
  435.     return MSG_NOERR;
  436. }
  437.  
  438.  
  439.  
  440.  
  441. int _fastcall put_mess (XMSG *msg,unsigned int areano,unsigned int messno) {
  442.  
  443.  /* write XMSG *msg to message #messno in area #areano */
  444.  
  445.     int          handle;
  446.     unsigned int x = 0;
  447.     char         filename[257];
  448.  
  449.  
  450.     if (messno < 1) return MSG_BADNUM;
  451.  
  452.     /* open data file */
  453.  
  454.     sprintf(filename,"%sXDATA.%03x",msgpath,areano);
  455.     while ((handle = sopen(filename,O_RDWR | O_BINARY | O_CREAT, SH_DENYNO,S_IWRITE | S_IREAD)) == -1) {
  456.         if (errno == EACCES) {
  457.             x++;
  458.             if(x > 9) {
  459.                 return MSG_NOACCESS;
  460.             }
  461.             DosSleep(1000L);
  462.          }
  463.          else {
  464.             return MSG_NOOPEN;
  465.          }
  466.     }
  467.  
  468.     /* seek to position */
  469.  
  470.     x = 0;
  471.     while (lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET) == -1L) {
  472.         x++;
  473.         if(x > 9) {
  474.             close(handle);
  475.             return MSG_NOSEEK;
  476.         }
  477.     }
  478.  
  479.     /* lock, write, unlock */
  480.  
  481.     if(!locking(handle,LK_LOCK,(long)sizeof(XMSG))) {
  482.         write(handle,msg,sizeof(XMSG));
  483.         lseek(handle,(long)((long)(messno - 1) * (long)sizeof(XMSG)),SEEK_SET);
  484.         locking(handle,LK_UNLCK,(long)sizeof(XMSG));
  485.         close(handle);
  486.         return MSG_NOERR;
  487.     }
  488.  
  489.     close(handle);
  490.     return MSG_NOLOCK;
  491. }
  492.  
  493.  
  494.  
  495. int _fastcall post_message (XMSG *msg,char **hold,unsigned int areano,
  496.                             int isfile) {
  497.  
  498.     /* post a new message given header, text and area #.  if isfile is
  499.        non-zero, **hold is name of file containing text to import (note
  500.        that hold must be malloced and freeable).  text imported from a
  501.        file will be treated here; text sent in *hold will not. */
  502.  
  503.     struct stat  st;
  504.     char         filename[257],*tempo;
  505.     unsigned int nomess;
  506.     int          ret;
  507.  
  508.  
  509.     if(!hold || !*hold || !**hold) return MSG_NOTEXT;
  510.  
  511.     sprintf("%sXDATA.%03x",msgpath,areano);
  512.     if(stat(filename,&st)) st.st_size = 0L;
  513.     nomess = (unsigned int)(st.st_size / (long)sizeof(XMSG));
  514.  
  515.     if(isfile) {    /* load a file for msg text */
  516.         strcpy(filename,*hold);
  517.         free(*hold);
  518.         *hold = NULL;
  519.         ret = sopen(filename,O_RDONLY | O_BINARY, SH_DENYNO,S_IWRITE | S_IREAD);
  520.         if(ret == -1) return MSG_NOTEXT;
  521.         lseek(ret,0L,SEEK_END);
  522.         st.st_size = tell(ret);
  523.         if(!st.st_size) {
  524.             close(ret);
  525.             return MSG_NOTEXT;
  526.         }
  527.         if(st.st_size > 65500L) st.st_size = 65500L;
  528.         *hold = (char *)malloc((unsigned int)st.st_size + 1);
  529.         if(!*hold) {
  530.             close(ret);
  531.             return MSG_NOMEM;
  532.         }
  533.         lseek(ret,0L,SEEK_SET);
  534.         if((unsigned int)read(ret,*hold,(unsigned int)st.st_size) !=
  535.            (unsigned int)st.st_size) {
  536.             close(ret);
  537.             free(*hold);
  538.             *hold = NULL;
  539.             return MSG_NOREAD;
  540.         }
  541.         close(ret);
  542.         tempo = *hold;      /* "treat" text */
  543.         tempo[(unsigned int)st.st_size] = 0;
  544.         msg->length = strlen(tempo);
  545.         while (*tempo) {
  546.             if(*tempo == '\x8d' || *tempo == '\n') {
  547.                 memmove(tempo,&tempo[1],msg->length - ((unsigned int)tempo -
  548.                         (unsigned int)*hold));
  549.                 msg->length--;
  550.                 if(!msg->length) {
  551.                     return MSG_NOTEXT;
  552.                 }
  553.             }
  554.             else tempo++;
  555.         }
  556.         if(*(tempo - 1) != '\r' && tempo > *hold) {
  557.             *tempo = '\r';
  558.             tempo[1] = 0;
  559.         }
  560.     }
  561.  
  562.     ret = append_text(msg,*hold,areano,nomess + 1);
  563.     if(ret == MSG_NOERR) {
  564.         return put_mess(msg,areano,nomess + 1);
  565.     }
  566.     return ret;
  567. }
  568.  
  569.  
  570.  
  571.  
  572. #ifdef __TURBOC__
  573.  
  574. int pascal locking (int handle,int type,long length) {
  575.  
  576.     int x;
  577.  
  578.  
  579.     if(type == LK_LOCK) {
  580.         x = 0;
  581.         while(x < 10) {
  582.             if(!lock(handle,tell(handle),length)) return 0;
  583.             x++;
  584.             DosSleep(1000L);
  585.         }
  586.     }
  587.     else if(type == LK_UNLCK) {
  588.         return unlock(handle,tell(handle),length);
  589.     }
  590.     return -1;
  591. }
  592.  
  593. #endif
  594.